package mySwingToolkit.ui;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;

import java.awt.BorderLayout;
import javax.swing.ListSelectionModel;
import javax.swing.border.LineBorder;
import java.awt.Color;
import java.util.ArrayList;

import java.util.List;

import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;


import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
import java.awt.Component;
import java.awt.ComponentOrientation;
import javax.swing.JToggleButton;
import java.awt.Cursor;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import javax.swing.JPopupMenu;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JMenuItem;

import mySwingToolkit.controller.TableController;
import mySwingToolkit.model.ClassModel;
import mySwingToolkit.model.SwitchedTableModel;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
/**
 * 带分页的表，
 * 表的模型为
 * 第一列是隐藏列，内置该行数据的类。通过translate方法将该类翻译成一行的object[].
 * @author hxd
 *
 */
public  class TableView<T> extends JPanel {
	/**
	 * 
	 */
	private static final long serialVersionUID = 7391786430413443600L;

	private JTable table;

	private JTextField currentPageText;
	private JToggleButton editButton;

	private SwitchedTableModel<T> tm;
	private TableController<T> tc;
	private JLabel totalPageText;
	private JButton nextButton;
	private JButton preButton;
	private JPopupMenu popupMenu;
	private JMenuItem deleteMenuItem;
	private JPanel panel;
	private JPanel panel_2;
	private JButton btnSaveButton;
	private JButton btnBackButton;
	private boolean canDelete=true;
	public TableView(SwitchedTableModel<T> tableModel,boolean canDelete){
		this();
		this.tm=tableModel;
		this.canDelete=canDelete;
		table.setOpaque(false);
		table.setDoubleBuffered(true);
		table.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
		this.table.setModel(tm);
		table.getColumnModel().getColumn(0).setResizable(false);
		table.getColumnModel().getColumn(0).setPreferredWidth(0);
		table.getColumnModel().getColumn(0).setMinWidth(0);
		table.getColumnModel().getColumn(0).setMaxWidth(0);
		table.setBorder(new LineBorder(new Color(0, 0, 0)));
		table.setColumnSelectionAllowed(true);
		table.setCellSelectionEnabled(true);
		table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		int j=0;
		for(boolean b:tableModel.getColumnEditables()){
			j++;
			if(b){
				break;
			}
		}
		if(j==tableModel.getColumnEditables().length){
			panel_2.remove(this.editButton);
			this.btnBackButton.setVisible(false);
			this.btnSaveButton.setVisible(false);
		}
		TableColumnModel tcm = table.getColumnModel();
		for (int i = 0, n = tcm.getColumnCount(); i < n; i++) {
			TableColumn tc = tcm.getColumn(i);
			tc.setCellRenderer(new RowRenderer<T>());
		}
		if(!this.canDelete){
			table.removeMouseListener(popMouseAdapter);
		}
	}

	//	public TableView(SwitchedTableModel<T> tableModel,TableController<T> tc){
	//		this(tableModel);
	//		this.tc=tc;
	//		if(this.tc!=null){
	//			tm.addTableModelListener(this.tc);
	//		}
	//	}
	//	public TableView(SwitchedTableModel<T> tableModel,List<T> datas){
	//		this(tableModel);
	//		this.initDatas(datas);
	//	}
	//	public TableView(SwitchedTableModel<T> tableModel,TableController<T> tc,List<T> datas){
	//		this(tableModel,tc);
	//		this.initDatas(datas);
	//	}

	/**
	 * 增加tableController
	 */
	public void setTableController(TableController<T> tc){
		this.tc=tc;
		tm.addTableModelListener(tc);
	}
	/**
	 * Create the panel.
	 */	private TableView() {
		setLayout(new BorderLayout(0, 0));

		JScrollPane scrollPane = new JScrollPane();
		add(scrollPane, BorderLayout.CENTER);

		table = new JTable();
		scrollPane.setViewportView(table);

		popupMenu = new JPopupMenu();
		addPopup(table, popupMenu);

		deleteMenuItem = new JMenuItem("删除");
		deleteMenuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				deleteMenuItemEvent(e);
			}
		});
		popupMenu.add(deleteMenuItem);


		panel = new JPanel();
		add(panel, BorderLayout.SOUTH);

		preButton = new JButton("上一页");
		preButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				prePage();
			}
		});

		nextButton = new JButton("下一页");
		nextButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				nextPage();
			}
		});

		JPanel panel_1 = new JPanel();

		btnBackButton = new JButton("撤销");
		btnBackButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				backupButtonEvent(e);
			}
		});

		btnSaveButton = new JButton("保存");
		btnSaveButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				saveButtonEvent(e);
				tm.getInsertDatas().clear();
				tm.getUpdateDatas().clear();
				tm.getDeleteDatas().clear();
			}
		});
		GroupLayout gl_panel = new GroupLayout(panel);
		gl_panel.setHorizontalGroup(
				gl_panel.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel.createSequentialGroup()
						.addGap(22)
						.addGroup(gl_panel.createParallelGroup(Alignment.TRAILING)
								.addComponent(btnSaveButton, 0, 0, Short.MAX_VALUE)
								.addComponent(btnBackButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
								.addGap(32)
								.addComponent(preButton, GroupLayout.DEFAULT_SIZE, 79, Short.MAX_VALUE)
								.addGap(72)
								.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, 104, GroupLayout.PREFERRED_SIZE)
								.addGap(84)
								.addComponent(nextButton, GroupLayout.DEFAULT_SIZE, 79, Short.MAX_VALUE)
								.addGap(88))
				);
		gl_panel.setVerticalGroup(
				gl_panel.createParallelGroup(Alignment.TRAILING)
				.addGroup(gl_panel.createSequentialGroup()
						.addGroup(gl_panel.createParallelGroup(Alignment.LEADING)
								.addGroup(gl_panel.createSequentialGroup()
										.addGap(27)
										.addComponent(preButton, GroupLayout.DEFAULT_SIZE, 25, Short.MAX_VALUE)
										.addGap(5))
										.addGroup(gl_panel.createSequentialGroup()
												.addGap(21)
												.addComponent(panel_1, GroupLayout.PREFERRED_SIZE, 36, Short.MAX_VALUE))
												.addGroup(gl_panel.createSequentialGroup()
														.addGap(27)
														.addComponent(nextButton)
														.addPreferredGap(ComponentPlacement.RELATED, 7, Short.MAX_VALUE)))
														.addGap(22))
														.addGroup(Alignment.LEADING, gl_panel.createSequentialGroup()
																.addContainerGap()
																.addComponent(btnBackButton, GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE)
																.addPreferredGap(ComponentPlacement.RELATED)
																.addComponent(btnSaveButton, GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE)
																.addGap(17))
				);

		totalPageText = new JLabel("/-");

		currentPageText = new JTextField();
		currentPageText.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				currentPageTextEvent(e);

			}
		});
		currentPageText.setAlignmentY(Component.TOP_ALIGNMENT);
		currentPageText.setAlignmentX(Component.LEFT_ALIGNMENT);
		currentPageText.setText("1");
		currentPageText.setColumns(10);
		GroupLayout gl_panel_1 = new GroupLayout(panel_1);
		gl_panel_1.setHorizontalGroup(
				gl_panel_1.createParallelGroup(Alignment.LEADING)
				.addGroup(gl_panel_1.createSequentialGroup()
						.addContainerGap(25, Short.MAX_VALUE)
						.addComponent(currentPageText, GroupLayout.PREFERRED_SIZE, 28, GroupLayout.PREFERRED_SIZE)
						.addPreferredGap(ComponentPlacement.RELATED)
						.addComponent(totalPageText, GroupLayout.PREFERRED_SIZE, 34, GroupLayout.PREFERRED_SIZE)
						.addContainerGap())
				);
		gl_panel_1.setVerticalGroup(
				gl_panel_1.createParallelGroup(Alignment.TRAILING)
				.addGroup(gl_panel_1.createSequentialGroup()
						.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
						.addGroup(gl_panel_1.createParallelGroup(Alignment.BASELINE)
								.addComponent(totalPageText, GroupLayout.PREFERRED_SIZE, 20, GroupLayout.PREFERRED_SIZE)
								.addComponent(currentPageText, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
								.addGap(6))
				);
		panel_1.setLayout(gl_panel_1);
		panel.setLayout(gl_panel);

		panel_2 = new JPanel();
		add(panel_2, BorderLayout.NORTH);
		panel_2.setLayout(new BorderLayout(0, 0));

		JLabel tableTitle = new JLabel("title",SwingConstants.CENTER);
		panel_2.add(tableTitle, BorderLayout.CENTER);

		editButton = new JToggleButton("点击进入编辑");
		editButton.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				editButtonEvent(e);
			}
		});
		editButton.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
		editButton.setToolTipText("选择是否允许编辑表格");
		panel_2.add(editButton, BorderLayout.EAST);
	}
	public JTable getTable() {
		return table;
	}
	/**
	 * 保存按钮是否可用
	 * @return
	 */
	protected boolean controlSaveButtonEnable() {
		if(tm!=null&&
				tm.getInsertDatas().size()==0
				&&tm.getDeleteDatas().size()==0
				&&tm.getUpdateDatas().size()==0)
			return false;
		else{
			return true;
		}
	}

	/**
	 * 启动编辑按钮的事件
	 * @param e
	 */
	protected void editButtonEvent(ChangeEvent e) {
		if(editButton.isSelected()){
			editButton.setText("编辑开启中");
			tm.setEditSwitch(true);
		}else{
			editButton.setText("点击进入编辑");
			tm.setEditSwitch(false);
		}		
	}
	/**
	 * 保存按钮的事件
	 * @param e
	 */
	protected void saveButtonEvent(ActionEvent e) {
		if(tc!=null)
			if(tc.saveChanges(tm)){
				JOptionPane.showMessageDialog(this, "保存成功！");
			}else{
				JOptionPane.showMessageDialog(this, "失败！");				
			}
	}
	/**
	 * 撤销按钮的事件
	 * @param e
	 */
	protected void backupButtonEvent(ActionEvent e) {
		if(tc!=null){
			tm.setCatchChangedEvent(false);
			initDatas(tc.getBackupDatas(tm));
			tm.setCatchChangedEvent(true);
		}
	}
	/**
	 * “删除”菜单的事件
	 * @param e
	 */
	protected void deleteMenuItemEvent(ActionEvent e) {
		@SuppressWarnings("unchecked")
		SwitchedTableModel<T> tm=((SwitchedTableModel<T>)table.getModel());
		if(table.getSelectedRow()==-1){
			JOptionPane.showMessageDialog(this, "必须先选中行 才可删除");
		}
		else{
			int deleteRows[]=table.getSelectedRows();
			tc.deleteRows(deleteRows,tm);
			for(int dr=deleteRows.length-1;dr>=0;dr--){
				//TODO
				//tm.removeRow(deleteRows[dr]);
			}
		}
	}
	/**
	 * 跳转输入框的事件
	 * @param e
	 */
	protected void currentPageTextEvent(KeyEvent e){
		if(e.getKeyCode()==KeyEvent.VK_ENTER){
			int page;
			try{
				page=Integer.valueOf(currentPageText.getText());
			}catch(NumberFormatException ne){
				page=1;
			}
			if(page>tm.getTotalPage()){
				page=tm.getTotalPage();
			}else if(page<1){
				page=1;
			}
			gotoPage(page);
		}
	}
	/**
	 * 
	 * @param datas  初始数据
	 */
	public void initDatas(List<T> datas){
		List<ClassModel<T>> list=null;
		if(datas!=null){
			//TODO
			list=new ArrayList<ClassModel<T>>(datas.size());
			for(T d:datas){
				list.add(new ClassModel<T>(d));
			}
		}
		else{
			list=new ArrayList<ClassModel<T>>();
		}
		this.tm.resetDatas(list);
		this.totalPageText.setText("/ "+this.tm.getTotalPage());	

		//设置翻页按钮的可用性
		if(this.tm.getTotalPage()==0){
			this.preButton.setEnabled(false);
			this.nextButton.setEnabled(false);
		}
		this.nextPage();		
	}
	/**
	 * 载入下一页数据<br>
	 * 通过调用model的方法进行数据修改，同时修改了页面显示和按钮状态
	 */
	public void nextPage(){
		this.tm.nextPage();
		this.currentPageText.setText(this.tm.getCurrentPage()+"");
		this.resetButtonState();
	}
	/**
	 * 载入前一页数据<br>
	 * 通过调用model的方法进行数据修改，同时修改了页面显示和按钮状态
	 */
	public void prePage(){
		this.tm.prePage();
		this.currentPageText.setText(this.tm.getCurrentPage()+"");
		this.resetButtonState();		
	}
	/**
	 * 载入特定页数据<br>
	 * 通过调用model的方法进行数据修改，同时修改了页面显示和按钮状态
	 **/
	public void gotoPage(int page){
		this.tm.gotoPage(page);
		this.currentPageText.setText(this.tm.getCurrentPage()+"");
		this.resetButtonState();
	}
	/**
	 * 重置翻页按钮状态
	 */
	public void resetButtonState(){
		if(this.tm.getCurrentPage()==1){
			this.preButton.setEnabled(false);
		}else{
			this.preButton.setEnabled(true);
		}
		if(this.tm.getCurrentPage()==this.tm.getTotalPage()){
			this.nextButton.setEnabled(false);
		}else{
			this.nextButton.setEnabled(true);
		}
	}


	private MouseAdapter popMouseAdapter;
	/**
	 * 右键菜单
	 * @param component
	 * @param popup
	 */

	private  void addPopup(Component component, final JPopupMenu popup) {
		popMouseAdapter=new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				if (e.isPopupTrigger()) {
					showMenu(e);
				}
			}
			public void mouseReleased(MouseEvent e) {
				if (e.isPopupTrigger()) {
					showMenu(e);
				}
			}
			private void showMenu(MouseEvent e) {
				if(editButton.isSelected())
					popup.show(e.getComponent(), e.getX(), e.getY());
			}
		};
		component.addMouseListener(popMouseAdapter);
	}
}
